// Fill out your copyright notice in the Description page of Project Settings.

#include "WorldEntityChangeset.h"
#include "WorldEntityManager.h"
#include <unordered_map>

FWorldEntityChangeset::FWorldEntityChangeset()
{
	// An empty changeset.
	_json = "{"
			"  \"add\": {"
			"    \"elements\": []"
			"  },"
			"  \"edit\": {"
			"    \"elements\": []"
			"  },"
			"  \"delete\": {"
			"    \"elements\": []"
			"  }"
			"}"_json;
}

FWorldEntityChangeset::~FWorldEntityChangeset()
{}

void FWorldEntityChangeset::Add(const FWorldEntity::Ptr& entity)
{
	json& jsonObj = _json["add"];
	if (jsonObj.is_array())
	{
		jsonObj.push_back(entity->ToJson());
	}
}

void FWorldEntityChangeset::Edit(const FWorldEntity::Ptr& entity)
{
	json& jsonObj = _json["edit"];
	if (jsonObj.is_array())
	{
		jsonObj.push_back(entity->ToJson());
	}
}

void FWorldEntityChangeset::Remove(const FWorldEntity::Ptr& entity)
{
	json& jsonObj = _json["delete"];
	if (jsonObj.is_array())
	{
		jsonObj.push_back(entity->ID.Get());
	}
}

void FWorldEntityChangeset::MapId(const json& res, const std::unordered_set<FWorldEntity::Ptr>& entities)
{
	std::unordered_map<std::int64_t, std::int64_t> idmapping;

	// IDs in one changeset is unique among entities.
	auto collectIds = [&](const json& j) {
		// IDs are interleaved in the forms of [fromId, toId, fromId, toId, ..]
		std::int64_t fromId = 0;
		for (const auto& ids : j)
		{
			if (fromId == 0) fromId = ids;
			else { idmapping[fromId] = ids; fromId = 0; }
		}
	};
	collectIds(res["idMapping"]);

	for (auto& entity : entities)
	{
		const std::int64_t fromId = entity->ID.Get();
		if (fromId < 0)
		{
			// fromId -> toId
			auto it = idmapping.find(fromId);
			if (it != idmapping.end())
			{
				entity->ID.Get() = it->second;
			}
		}
	}
}

const json& FWorldEntityChangeset::Json() const
{
	return _json;
}
